#pragma once

#include <string>
#include <hash_map>
#include <map>
#include <set>
#include <wx/treectrl.h>
#include "TagStorage.h"

class wxImageList;
class wxTreeItemId;

class ClassTree : public wxTreeCtrl{
public:

	ClassTree(wxWindow* parent, wxWindowID id = wxID_ANY,
			  const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
	~ClassTree();

	bool Create(wxWindow* parent, wxWindowID id = wxID_ANY,
				const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);

	void rebuild();
	void update();
	void setFilter(const char* filter, const char* memberFilter);

	const Tag* selectedTag() const{ return selectedTag_; }

	void serialize(Archive& ar);
protected:

	typedef vector<wxTreeItemId> Items;
	struct ClassInfo{
		ClassInfo() : hasChildren(false) {}
        wxTreeItemId ghostItem;
		Items items;
		bool hasChildren;
	};


	// add new tag, possibly in existing node
	int addTag(const Tag* tag);
	// remove dead tag
	void removeTag(const Tag* tag);
	void removeEmptyGhosts();
	int countTagItems(const Tag* tag);

	void Delete(wxTreeItemId item, bool dead = false);

	void verifyItem(wxTreeItemId item);
	void verifyTree(wxTreeItemId root);

	void onSelectionChanged(wxTreeEvent& event);
	void onKeyDown(wxKeyEvent& event);

	Items findItemsWithTag(const Tag* tag);
	wxTreeItemId insertTagItemSorted(wxTreeItemId parent, const char* title, TagType type);

	bool canBeParent(TagType type) const;
	ClassInfo* findOrAddParentInfo(const Tag* tag);
	void addParentInfo(const Tag* tag, wxTreeItemId item);
	ClassInfo* insertGhostClassItem(const char* nameFull);

	// returns if it safe to delete item
	bool removeTagFromItem(wxTreeItemId item, const Tag* tag);
    void addTagToItem(wxTreeItemId item, const Tag* tag);

	bool matchFilter(const Tag& tag, bool forRoot);
	bool matchFilter(const char* ghostClassName);
	bool refilter(wxTreeItemId root);

	const Tag* tagByItem(wxTreeItemId item, bool wantDeclaration = false);
	//wxTreeItemId itemByTag(const Tag* tag, bool eraseFounded = false);
	const Tag* selectedTag_;

	typedef std::map<const Tag*, Items> ItemsByTag;
	ItemsByTag itemsByTag_;
	Items ghostItems_;

	wxImageList* imageList_;

	string filterMember_;
	string filter_;

	typedef stdext::hash_map<string, ClassInfo> ClassNameToInfoMap;
	ClassNameToInfoMap classNameToInfo_;

    ClassInfo rootInfo_;

	DECLARE_EVENT_TABLE()
};
